const express = require('express');
const WebSocket = require('ws');
const http = require('http');
const { BattleLogicRunner } = require('./battle-runner');
const { getLogger } = require('./logger');

class BattleServer {
    constructor(port = 3000, battleId = 'default') {
        this.port = port;
        this.battleId = battleId;
        this.app = express();
        this.server = http.createServer(this.app);
        this.wss = null;
        this.clients = new Map(); // clientId -> WebSocket
        this.battleRunner = new BattleLogicRunner(battleId);
        this.logger = getLogger(battleId);

        this.logger.info('SERVER', `Battle server created - Port: ${port}, Battle ID: ${battleId}`);

        this.setupRoutes();
        this.setupWebSocket();
    }

    setupRoutes() {
        this.app.use(express.json());

        // 健康检查
        this.app.get('/health', (req, res) => {
            res.json({
                status: 'ok',
                battleId: this.battleId,
                port: this.port,
                timestamp: new Date().toISOString(),
                connectedClients: this.clients.size,
            });
        });

        // 获取战斗状态
        this.app.get('/battle/status', (req, res) => {
            res.json({
                battleId: this.battleId,
                battleState: this.battleRunner.getBattleState(),
                connectedClients: this.clients.size,
            });
        });

        // 初始化战斗
        this.app.post('/battle/init', async (req, res) => {
            const startTime = Date.now();
            try {
                const initCommand = req.body;
                const requestBattleId = initCommand.battleId;

                this.logger.battleSystem('Initializing battle', {
                    ...initCommand,
                    requestBattleId: requestBattleId,
                    serverBattleId: this.battleId,
                });

                // 战斗ID验证 - 防止状态污染
                if (requestBattleId && requestBattleId !== this.battleId) {
                    const errorMsg = `战斗ID不匹配 - 服务器战斗ID: ${this.battleId}, 请求战斗ID: ${requestBattleId}`;
                    this.logger.error('BATTLE_INIT', errorMsg, {
                        serverBattleId: this.battleId,
                        requestBattleId: requestBattleId,
                    });
                    return res.status(400).json({
                        success: false,
                        error: errorMsg,
                        code: 'BATTLE_ID_MISMATCH',
                        battleId: this.battleId,
                    });
                }

                // 初始化战斗系统
                const result = await this.battleRunner.initializeBattle(initCommand);

                const duration = Date.now() - startTime;

                if (result.success) {
                    this.logger.battleSystem(`Battle initialization successful (${duration}ms)`, {
                        initCommand: initCommand,
                        result: result,
                    });
                    res.json({
                        success: true,
                        message: result.message,
                        initCommand: initCommand,
                        battleId: this.battleId,
                    });
                } else {
                    this.logger.error('BATTLE_INIT', `Battle initialization failed (${duration}ms)`, {
                        initCommand: initCommand,
                        error: result.message,
                    });
                    res.status(500).json({
                        success: false,
                        error: result.message,
                    });
                }
            } catch (error) {
                const duration = Date.now() - startTime;
                this.logger.error('BATTLE_INIT', `Battle initialization exception (${duration}ms)`, {
                    error: error.message,
                    stack: error.stack,
                });
                res.status(500).json({
                    success: false,
                    error: error.message,
                });
            }
        });

        // 执行战斗命令
        this.app.post('/battle/execute', async (req, res) => {
            const requestStartTime = Date.now();
            try {
                const commandsData = req.body;
                const playerID = commandsData.playerID;
                const commands = commandsData.commands;
                const requestBattleId = commandsData.battleId;
                const codeExecutionFailed = commandsData.codeExecutionFailed || false;

                this.logger.info('SERVER', '=== 开始处理命令执行请求 ===', {
                    requestTime: new Date().toISOString(),
                    playerID: playerID,
                    commandCount: commands.length,
                    dataSize: JSON.stringify(commandsData).length,
                    requestBattleId: requestBattleId,
                    serverBattleId: this.battleId,
                    codeExecutionFailed: codeExecutionFailed,
                });

                // 战斗ID验证 - 防止状态污染
                if (requestBattleId && requestBattleId !== this.battleId) {
                    const errorMsg = `战斗ID不匹配 - 服务器战斗ID: ${this.battleId}, 请求战斗ID: ${requestBattleId}`;
                    this.logger.error('SERVER', errorMsg, {
                        serverBattleId: this.battleId,
                        requestBattleId: requestBattleId,
                        playerID: playerID,
                    });
                    return res.status(400).json({
                        success: false,
                        error: errorMsg,
                        code: 'BATTLE_ID_MISMATCH',
                        battleId: this.battleId,
                    });
                }

                // 执行命令
                this.logger.info('SERVER', '开始执行命令...');

                // 执行单个玩家的命令
                const result = await this.battleRunner.executeRound(playerID, commands, codeExecutionFailed);

                const requestDuration = Date.now() - requestStartTime;
                this.logger.info('SERVER', `回合执行完成 (${requestDuration}ms)`, {
                    success: result.success,
                    round: result.round,
                    battleEnded: result.battle_ended,
                    winner: result.winner,
                });

                this.logger.info('SERVER', `=== 玩家 ${playerID} 回合执行请求处理完成 ===`);

                res.json(result);
            } catch (error) {
                const requestDuration = Date.now() - requestStartTime;
                this.logger.error('SERVER', `战斗执行错误 (${requestDuration}ms)`, {
                    errorType: error.name,
                    errorMessage: error.message,
                    stack: error.stack,
                });
                res.status(500).json({
                    success: false,
                    error: error.message,
                });
            }
        });
    }

    setupWebSocket() {
        // WebSocket设置将在start方法中完成
    }

    handleConnection(ws) {
        const clientId = this.generateClientId();
        this.clients.set(clientId, ws);

        this.logger.info('SERVER', `Client ${clientId} connected to battle ${this.battleId}`);

        ws.on('message', (data) => {
            this.handleMessage(clientId, data);
        });

        ws.on('close', () => {
            this.logger.info('SERVER', `Client ${clientId} disconnected from battle ${this.battleId}`);
            this.clients.delete(clientId);
        });

        ws.on('error', (error) => {
            this.logger.error('SERVER', `WebSocket error for client ${clientId}`, {
                error: error.message,
                stack: error.stack,
            });
            this.clients.delete(clientId);
        });
    }

    handleMessage(clientId, data) {
        // 解析消息
        let message;
        try {
            message = JSON.parse(data);
        } catch (error) {
            this.logger.error('SERVER', `解析消息失败 - Client ${clientId}`, {
                error: error.message,
                rawData: data.toString(),
            });
            return;
        }

        this.logger.info('SERVER', `收到消息 - Client ${clientId}`, message);

        // 处理不同类型的消息
        if (message.type === 'command') {
            // 直接使用CommandModel格式
            const command = message.command;

            this.logger.info('SERVER', `执行WebSocket命令 - Client ${clientId}`, command);

            // 执行命令
            const result = this.battleRunner.executeCommand(command);

            // 广播命令执行结果给所有客户端
            this.broadcast(result);
        } else if (message.type === 'ping') {
            this.handlePing(clientId);
        } else {
            this.logger.warn('SERVER', `Unknown message type: ${message.type} - Client ${clientId}`, message);
        }
    }

    handleCommand(clientId, message) {
        const { command } = message;

        if (!command) {
            this.sendToClient(clientId, {
                type: 'error',
                message: 'Command is required',
            });
            return;
        }

        // 直接将命令传递给战斗逻辑运行器
        const result = this.battleRunner.executeCommand(command);

        // 广播命令执行结果给所有客户端
        this.broadcast({
            type: 'command_result',
            command: command,
            result: result,
            timestamp: Date.now(),
        });
    }

    handlePing(clientId) {
        this.sendToClient(clientId, {
            type: 'pong',
            timestamp: Date.now(),
        });
    }

    sendToClient(clientId, message) {
        const ws = this.clients.get(clientId);
        if (ws && ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify(message));
        }
    }

    broadcast(message, excludeClientId = null) {
        this.clients.forEach((ws, clientId) => {
            if (clientId !== excludeClientId && ws.readyState === WebSocket.OPEN) {
                ws.send(JSON.stringify(message));
            }
        });
    }

    generateClientId() {
        return 'client_' + Math.random().toString(36).substr(2, 9) + '_' + Date.now();
    }

    async start() {
        try {
            // 初始化战斗逻辑运行器
            await this.battleRunner.initialize();

            // 启动HTTP服务器
            this.server.listen(this.port, () => {
                console.log(`Battle server ${this.battleId} listening on port ${this.port}`);
            });

            // 启动WebSocket服务器
            this.wss = new WebSocket.Server({ server: this.server });

            this.wss.on('connection', (ws) => {
                this.handleConnection(ws);
            });

            console.log(`Battle server ${this.battleId} started successfully`);
        } catch (error) {
            console.error(`Failed to start battle server ${this.battleId}:`, error);
            throw error;
        }
    }

    stop() {
        return new Promise((resolve) => {
            // 关闭所有WebSocket连接
            this.clients.forEach((client) => {
                if (client.ws.readyState === WebSocket.OPEN) {
                    client.ws.close();
                }
            });

            // 清理战斗逻辑运行器
            if (this.battleRunner) {
                this.battleRunner.cleanup();
            }

            // 关闭服务器
            this.server.close(() => {
                console.log(`[Battle ${this.battleId}] Server stopped`);
                resolve();
            });
        });
    }
}

// 如果直接运行此文件
if (require.main === module) {
    const port = process.argv[2] || 3000;
    const battleId = process.argv[3] || 'test_battle';

    const server = new BattleServer(port, battleId);
    server.start().catch(console.error);

    // 优雅关闭
    process.on('SIGINT', async () => {
        console.log('Shutting down battle server...');
        await server.stop();
        process.exit(0);
    });
}

module.exports = { BattleServer };
